package com.shop.admin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shop.entity.dto.AdminArr.AdminSaveWaresStyleArr;
import com.shop.entity.dto.AdminWares.*;
import com.shop.entity.pojo.*;
import com.shop.admin.mapper.*;
import com.shop.admin.service.WaresService;
import com.shop.utils.common.enums.Code;
import com.shop.utils.common.enums.Message;
import com.shop.utils.common.result.PageResponseResult;
import com.shop.utils.common.result.Result;
import com.shop.utils.config.BaseContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;


@Service

public class WaresServiceImpl extends ServiceImpl<WaresMapper, Wares> implements WaresService{


    @Autowired
    private WaresMapper waresMapper;
    @Autowired
    private AdminUserMapper adminUserMapper;
    @Autowired
    private StyleMapper styleMapper;
    @Autowired
    private CostMapper costMapper;

    @Autowired
    private ImagesMapper waresImagesMapper;
    @Autowired
    private BrandsMapper brandsMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Result saveWares(AdminWaresSaveDto dto) {
        if (dto==null||dto.getHaveStyle()==null
        ||dto.getStyleArr().length==Message.Check_Int_Null) {
            return Result.errorResult(Code.PARAM_REQUIRE);
        }
        Long adminId = BaseContext.getCurrentId();
        AdminUser adminUser = adminUserMapper.selectById(adminId);
        if (adminUser==null||adminId==null) {
            return Result.errorResult(Code.NEED_LOGIN);
        }
        Images waresImages = waresImagesMapper.selectById(dto.getWaresImagesId());
        List<Wares> checkWaresList = waresMapper.selectList(Wrappers.<Wares>lambdaQuery()
                .eq(Wares::getWaresName, dto.getWaresName()));
        List<Brands> checkBrands = brandsMapper.selectList(Wrappers.<Brands>lambdaQuery()
                .eq(Brands::getId, dto.getBrandsId()));
        if (checkWaresList!=null&&checkWaresList.size()> Message.Check_Int_Null) {
            return Result.errorResult(Code.DATA_EXIST);
        }
        if (checkBrands==null&&checkBrands.size()== Message.Check_Int_Null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        String k=Message.WeChat_Key_Wares_All;
        String k2=Message.WeChat_Key_Brands+dto.getBrandsId();
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        Wares wares=new Wares();
        wares=wares.builder()
                .waresName(dto.getWaresName())
                .waresImages(waresImages.getUrl())
                .brandsId(dto.getBrandsId())
                .saveAdmin(adminUser.getName())
                .saveTime(String.valueOf(LocalDateTime.now()))
                .build();
        int checkWares = waresMapper.saveWares(wares);
        if (checkWares== Message.Check_Int_False) {
            return Result.errorResult(Code.SERVER_ERROR);
        }

        Style style=new Style();
        Cost cost=new Cost();

        if (dto.getHaveStyle().equals(Message.Check_String_True)) {
            for (AdminSaveWaresStyleArr styleArr : dto.getStyleArr()) {
                Images styleImages = waresImagesMapper.selectById(styleArr.getStyleImages());
                style=style.builder()
                        .waresId(wares.getId())
                        .styleName(styleArr.getStyleName())
                        .styleImages(styleImages.getUrl())
                        .saveAdmin(adminUser.getName())
                        .saveTime(String.valueOf(LocalDateTime.now())).build();
                int checkStyle = styleMapper.saveStyle(style);
                if (checkStyle== Message.Check_Int_False) {
                    waresMapper.deleteById(wares);
                    return Result.errorResult(Code.SERVER_ERROR);
                }
                cost=cost.builder()
                        .waresId(wares.getId())
                        .styleId(style.getId())
                        .costMessage(styleArr.getCostMessage())
                        .waresPrice(styleArr.getWaresPrice())
                        .saveAdmin(adminUser.getName())
                        .saveTime(String.valueOf(LocalDateTime.now())).build();
                int checkCost = costMapper.insert(cost);
                if (checkCost== Message.Check_Int_False) {
                    waresMapper.deleteById(wares);
                    styleMapper.deleteById(style);
                    return Result.errorResult(Code.SERVER_ERROR);
                }
            }
        } else if (dto.getHaveStyle().equals(Message.Check_String_False)) {
            style= style.builder()
                    .waresId(wares.getId())
                    .styleName(wares.getWaresName())
                    .styleImages(wares.getWaresImages())
                    .saveAdmin(adminUser.getName())
                    .saveTime(String.valueOf(LocalDateTime.now())).build();
            int checkStyle = styleMapper.saveStyle(style);
            if (checkStyle== Message.Check_Int_False) {
                waresMapper.deleteById(wares);
                return Result.errorResult(Code.SERVER_ERROR);
            }
            cost=cost.builder()
                    .waresId(wares.getId())
                    .styleId(style.getId())
                    .costMessage(dto.getCostMessage())
                    .waresPrice(dto.getWaresPrice())
                    .saveAdmin(adminUser.getName())
                    .saveTime(String.valueOf(LocalDateTime.now())).build();
            int checkCost = costMapper.insert(cost);
            if (checkCost== Message.Check_Int_False) {
                waresMapper.deleteById(wares);
                styleMapper.deleteById(style);
                return Result.errorResult(Code.SERVER_ERROR);
            }
        }else {
            return Result.errorResult(Code.PARAM_INVALID);
        }
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        return Result.okResult(Code.SUCCESS);
    }

    @Override
    public Result removeWares(AdminWaresRemoveDto dto) {
        if (dto==null) {
            return Result.errorResult(Code.PARAM_REQUIRE);
        }
        Long adminId = BaseContext.getCurrentId();
        AdminUser adminUser = adminUserMapper.selectById(adminId);
        if (adminId==null||adminUser==null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        Wares wares = waresMapper.selectById(dto.getWaresId());
        if (wares==null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        String k=Message.WeChat_Key_Wares_All;
        String k2=Message.WeChat_Key_Brands+wares.getBrandsId();
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        List<Style> styleList = styleMapper.selectList(Wrappers.<Style>lambdaQuery().eq(Style::getWaresId, dto.getWaresId()));
        List<Cost> costList = costMapper.selectList(Wrappers.<Cost>lambdaQuery().eq(Cost::getWaresId, dto.getWaresId()));
        if (!CollectionUtils.isEmpty(styleList)
                ||styleList.size()>Message.Check_Int_Null
                ||!CollectionUtils.isEmpty(costList)
                ||costList.size()>Message.Check_Int_Null) {
            if (dto.getRemoveRelated().equals(Message.Check_String_True)) {
                boolean checkWares = removeWaresAsync(adminUser, dto);
                boolean checkStyle = removeWaresStyleAsync(adminUser, dto);
                boolean checkCost = removeWaresCostAsync(adminUser, dto);
                if (!checkWares||!checkStyle||!checkCost) {
                    return Result.errorResult(Code.SERVER_ERROR);
                }else {
                    return Result.okResult(Code.SUCCESS);
                }
            }else if (dto.getRemoveRelated().equals(Message.Check_String_False)){
                return Result.errorResult(Code.DATA_EXIST);
            }
            else {
                return Result.errorResult(Code.PARAM_INVALID);
            }
        }
        boolean checkWares = removeWaresAsync(adminUser, dto);
        if (!checkWares) {
            return Result.errorResult(Code.SERVER_ERROR);
        }
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        return Result.okResult(Code.SUCCESS);
    }


    @Override
    public Result openWares(AdminWaresOpenDto dto) {
        if (dto==null) {
            return Result.errorResult(Code.PARAM_REQUIRE);
        }
        Long adminId = BaseContext.getCurrentId();
        AdminUser adminUser = adminUserMapper.selectById(adminId);
        Wares byId = waresMapper.getOne(dto.getWaresId());
        if (adminId==null||byId==null||adminUser==null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        if (byId.getIsDelete()==Message.Delete_True) {
            return Result.errorResult(Code.PARAM_INVALID);
        }
        String k=Message.WeChat_Key_Wares_All;
        String k2=Message.WeChat_Key_Brands+byId.getBrandsId();
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        Wares wares=new Wares();
        wares= wares.builder()
                .id(dto.getWaresId())
                .isDelete(Message.Delete_True)
                .removeAdmin(null)
                .removeMemo(null)
                .saveAdmin(adminUser.getName())
                .saveTime(String.valueOf(LocalDateTime.now()))
                .version(byId.getVersion()+Message.Version_Up).build();
        boolean update = waresMapper.updateDelete(wares);
        if (!update) {
            return Result.errorResult(Code.SERVER_ERROR);
        }
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        return Result.okResult(Code.SUCCESS);
    }

    @Override
    public Result updateWares(AdminWaresUpdateDto dto) {
        if (dto==null) {
            return Result.errorResult(Code.PARAM_REQUIRE);
        }
        Long adminId = BaseContext.getCurrentId();
        AdminUser adminUsers = adminUserMapper.selectOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, adminId));
        if (adminUsers==null||adminId==null) {
            return Result.errorResult(Code.PARAM_INVALID);
        }
        Wares oldWares = waresMapper.selectById(dto.getWaresId());
        if (oldWares==null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        String k=Message.WeChat_Key_Wares_All;
        String k2=Message.WeChat_Key_Brands+oldWares.getBrandsId();
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        String waresImgUrl= oldWares.getWaresImages();
        if (dto.getWaresImagesId()!=null) {
            Images waresImages = waresImagesMapper.selectById(dto.getWaresImagesId());
            if (waresImages==null) {
                return Result.errorResult(Code.DATA_NOT_EXIST);
            }
            waresImgUrl = waresImages.getUrl();
        }
        String waresName=oldWares.getWaresName();
        if (dto.getWaresName()!=null) {
            List<Wares> waresList = waresMapper.selectList(Wrappers.<Wares>lambdaQuery()
                    .eq(Wares::getWaresName, dto.getWaresName()));
            if (!CollectionUtils.isEmpty(waresList)||waresList.size()>Message.Check_Int_Null) {
                return Result.errorResult(Code.DATA_EXIST);
            }
            waresName= dto.getWaresName();
        }
        Wares wares=new Wares();
        wares=wares.builder()
                .waresName(waresName)
                .waresImages(waresImgUrl)
                .saveAdmin(adminUsers.getName()).build();

        boolean update = update(wares, Wrappers.<Wares>lambdaUpdate().eq(Wares::getId, dto.getWaresId()));
        if (!update) {
            return Result.errorResult(Code.SERVER_ERROR);
        }
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        return Result.okResult(Code.SUCCESS);
    }

    @Override
    public Result<Wares> updateGetWares(AdminWaresUpdateForGetDto dto) {
        if (dto==null) {
            return Result.errorResult(Code.PARAM_REQUIRE);
        }
        Wares wares = getOne(Wrappers.<Wares>lambdaQuery().eq(Wares::getId, dto.getWaresId()));
        if (wares==null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        return Result.okResult(wares);
    }

    @Override
    public Result pullWares(AdminWaresPullDto dto) {
        if (dto.getWaresId()==null||dto.getMemo()==null) {
            return Result.errorResult(Code.PARAM_REQUIRE);
        }
        Long userId = BaseContext.getCurrentId();
        AdminUser adminUser = adminUserMapper.selectById(userId);
        Wares checkWares = waresMapper.selectById(dto.getWaresId());
        if (userId==null||adminUser==null) {
            return Result.errorResult(Code.NEED_LOGIN);
        }
        if (checkWares==null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        String k=Message.WeChat_Key_Wares_All;
        String k2=Message.WeChat_Key_Brands+checkWares.getBrandsId();
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        boolean checkAsyncWares = pullWaresAsync(adminUser, dto);
        boolean checkAsyncStyle = pullStyleAsync(adminUser, dto);
        boolean checkAsyncCost = pullCostAsync(adminUser, dto);
        if (!checkAsyncWares||!checkAsyncStyle||!checkAsyncCost) {
            return Result.errorResult(Code.SERVER_ERROR);
        }
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        return Result.okResult(Code.SUCCESS);
    }

    @Override
    public Result putWares(AdminWaresPutDto dto) {

        if (dto==null) {
            return Result.errorResult(Code.PARAM_REQUIRE);
        }
        Long userId = BaseContext.getCurrentId();
        AdminUser adminUser = adminUserMapper.selectById(userId);
        if (userId==null||adminUser==null) {
            return Result.errorResult(Code.NEED_LOGIN);
        }
        Wares checkWares = waresMapper.selectById(dto.getWaresId());
        if (checkWares==null) {
            return Result.errorResult(Code.DATA_NOT_EXIST);
        }
        String k=Message.WeChat_Key_Wares_All;
        String k2=Message.WeChat_Key_Brands+checkWares.getBrandsId();
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        boolean checkAsyncWares = putWaresAsync(adminUser, dto);
        boolean checkAsyncStyle = putStyleAsync(adminUser,dto);
        boolean checkAsyncCost = putCostAsync(adminUser,dto);
        if (!checkAsyncWares||!checkAsyncStyle||!checkAsyncCost) {
            return Result.errorResult(Code.SERVER_ERROR);
        }
        redisTemplate.delete(k);
        redisTemplate.delete(k2);
        return Result.okResult(Code.SUCCESS);
    }

    @Override
    public Result getWaresList(AdminWaresListDto dto) {
        dto.checkParam();
        Page<Wares> page=new Page<>(dto.getPage(),dto.getSize());
        Page<Wares> value = waresMapper.getAllByPage(page, dto);
        Result result=new PageResponseResult(dto.getPage(),dto.getSize(), (int) value.getTotal());
        result.setData(value.getRecords());
        return Result.okResult(result);
    }


    /**
     * 异步
     */


    //put_wares
    @Async
    public boolean putWaresAsync(AdminUser adminUser,AdminWaresPutDto dto){
        boolean check=true;
        Wares wares=new Wares();
        wares= wares.builder()
                .state(Message.Put)
                .saveAdmin(adminUser.getName())
                .saveTime(String.valueOf(LocalDateTime.now())).build();
        int update = waresMapper.update(wares, Wrappers.<Wares>lambdaUpdate().eq(Wares::getId, dto.getWaresId()));
        if (update== Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }
    @Async
    public boolean putStyleAsync(AdminUser adminUser,AdminWaresPutDto dto){
        boolean check=true;
        Style style=new Style();
        style= style.builder()
                .state(Message.Put)
                .saveAdmin(adminUser.getName())
                .saveTime(String.valueOf(LocalDateTime.now())).build();
        int update = styleMapper.update(style, Wrappers.<Style>lambdaUpdate().eq(Style::getWaresId, dto.getWaresId()));
        if (update== Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }
    @Async
    public boolean putCostAsync(AdminUser adminUser,AdminWaresPutDto dto){
        boolean check=true;
        Wares wares=new Wares();
        wares= wares.builder()
                .state(Message.Put)
                .saveAdmin(adminUser.getName())
                .saveTime(String.valueOf(LocalDateTime.now())).build();
        int update = waresMapper.update(wares, Wrappers.<Wares>lambdaUpdate().eq(Wares::getId, dto.getWaresId()));
        if (update== Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }


    //pull_wares
    @Async
    public boolean pullWaresAsync(AdminUser adminUser,AdminWaresPullDto dto){
        boolean check=true;
        Wares wares=new Wares();
        wares= wares.builder()
                .state(Message.Pull)
                .removeAdmin(adminUser.getName())
                .removeMemo(dto.getMemo()).build();
        int update = waresMapper.update(wares, Wrappers.<Wares>lambdaUpdate().eq(Wares::getId, dto.getWaresId()));
        if (update== Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }
    @Async
    public boolean pullStyleAsync(AdminUser adminUser,AdminWaresPullDto dto){
        boolean check=true;
        Style style=new Style();
        style= style.builder()
                .state(Message.Pull)
                .removeAdmin(adminUser.getName())
                .removeMemo(dto.getMemo()).build();
        int update = styleMapper.update(style, Wrappers.<Style>lambdaUpdate().eq(Style::getWaresId, dto.getWaresId()));
        if (update== Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }
    @Async
    public boolean pullCostAsync(AdminUser adminUser,AdminWaresPullDto dto){
        boolean check=true;
        Cost cost=new Cost();
        cost= cost.builder()
                .state(Message.Pull)
                .removeAdmin(adminUser.getName())
                .removeMemo(dto.getMemo()).build();
        int update = costMapper.update(cost, Wrappers.<Cost>lambdaUpdate().eq(Cost::getWaresId, dto.getWaresId()));
        if (update== Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }



    //remove_wares
    @Async
    public boolean removeWaresAsync(AdminUser adminUser,AdminWaresRemoveDto dto){
        boolean check=true;
        Wares newWares=new Wares();
        newWares= newWares.builder()
                .removeMemo(dto.getRemoveMemo())
                .removeAdmin(adminUser.getName()).build();
        int update = waresMapper.update(newWares, Wrappers.<Wares>lambdaUpdate().eq(Wares::getId, dto.getWaresId()));
        int delete = waresMapper.deleteById(dto.getWaresId());
        if (update== Message.Check_Int_False||delete==Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }

    @Async
    public boolean removeWaresStyleAsync(AdminUser adminUser,AdminWaresRemoveDto dto){
        boolean check=true;
        Style style=new Style().builder()
                .removeAdmin(adminUser.getName())
                .removeMemo(dto.getRemoveMemo()).build();
        int update = styleMapper.update(style, Wrappers.<Style>lambdaQuery().eq(Style::getWaresId, dto.getWaresId()));
        int delete = styleMapper.delete(Wrappers.<Style>lambdaQuery().eq(Style::getWaresId, dto.getWaresId()));
        if (update== Message.Check_Int_False||delete==Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }
    @Async
    public boolean removeWaresCostAsync(AdminUser adminUser,AdminWaresRemoveDto dto){
        boolean check=true;
        Cost cost=new Cost().builder()
                .removeAdmin(adminUser.getName())
                .removeMemo(dto.getRemoveMemo()).build();
        int update = costMapper.update(cost, Wrappers.<Cost>lambdaQuery().eq(Cost::getWaresId, dto.getWaresId()));
        int delete = costMapper.delete(Wrappers.<Cost>lambdaQuery().eq(Cost::getWaresId, dto.getWaresId()));
        if (update== Message.Check_Int_False||delete==Message.Check_Int_False) {
            check=false;
            return check;
        }
        return check;
    }




}
